/*-------------------------------------------------------------------------*/
/**
  @file		pagrid_struct.h
  @author	Renaud Wanschoor
  @date	july 2004
  @version	$Revision: 2.10 $
  @brief	specific pargrid structure used by pagridplot

  this file is present in Lib and not in pagrid home directory (as in
  metis) to avoid the duplication of a file that is modified quiet often
  
*/
/*--------------------------------------------------------------------------*/

/*controlling macro*/
#ifndef HEADER_VERTEX_H_NOT_SEEN
#define HEADER_VERTEX_H_NOT_SEEN

/** \brief application graph structure */
typedef struct GraphType{
  /**********************
   * graph information
   *********************/
  Mem mem;		/**< memory */

  int wgtflag;		/**< whether the vertics are weighted*/
  int ncon;		/**< The # of constrains */ 
  int nvtxs, nedges;	/**< The # of vertices and edges in the graph */
  int maxdeg;		/**< maximum degree of a vertex */
  int *adjidx;		/**< Pointers to the locally stored vertices */
  int *vwgt;		/**< Vertex weights */
  int *adjncy;		/**< adjacency lists of nvtxs */
  int *adjwgt;		/**< weights of the adjacency lists */
  int *adjwgtsum;	/**< The sum of the adjacency weight of each vertex */
  
  /***********************
   * Matching information
   **********************/
  int *match;		/**< label with which a vertex is matched */
  int *map;		/**< label in the coarser graph */
  
  /**************************
   * Refinement information
   *************************/
  int *pro;		/**< Array holding the assigned processor to a vertex*/
  int *checked;

  /**************************
   * level browsing
   *************************/
  
  struct GraphType *child;	/**< pointer to child (coarser) graph*/
  struct GraphType *father;	/**< pointer to father (finer) graph*/

}GraphType;

/***************************************************************************/
/** \brief various parameters most of them come from the command line */
typedef struct PartInfoType {/*partitioning informatoin*/
  int WType;  /**< edge weight type during coarsening */
  int CType;  /**< matching scheme */
  int RType;  /**< uncoarsening method */
  int out[3]; /**< out[IO_RESULT] (no, multiple or single output), out[IO_ID] (id for multiple output), out[IO_SER] (need to serialize what was done or not)*/
  int PSeed;  /**< program random seed */
  int CSeed;  /**< coarsening random seed */
  int ISeed;  /**< initial partititoning random seed */
  int RSeed;  /**< uncoarsening random seed */
  int NBytes; /**< Number of bytes a vertex will send for communication, default is 10 */

  char F_output[256]; /**< output file for the partition */
  char *F_graph;      /**< application graph file */
  char *F_grid;       /**< computational grid file */
  char F_serialize[256]; /**< if the matching is to be readen from a file, this stores the name of this file */

  double cputime[5];	/**< Timing Record*/
  double rtimer[6];	/**< Record of time*/

  int level;            /**< number of levels */
  int currLevel;        /**< current level */
    
}PartInfoType;

/*************************************************************************
 * The following data structure stores grid information 
 ************************************************************************/
/** \brief computational grid structure */
typedef struct GridType {	/*<computationtional grid information*/
  int npro;			/**< Number of processors*/
  int nedges;			/**< Number of links*/

  Mem     mem;

  double **ratio;		/**< Ratio (Tcomm/Tcomp) matrix*/ 

  int    **connect;		/**< number of edges between two processors */
  int    **latency;		/**<latency between each pair of processors */
  int    **latency1;
  int**   convtxs;              /**< number of vertices that connecting to each pair of processor */
  int**   convtxs2;             /** temp number of vertices that connects to each pair of processor */
  int*    conproc;              /**< boolean for a processor connect to other processors */

  int*    adjidx;		/**< edge indexes */ 
  int*    adjncy;		/**< edges (destination processor) */
  int*    adjwgt;		/**< edges weight */
  int*    adjlcy;		/**< network latency weight */
  double* exec;                 /**< array of processors execution time */

  /**********************************/
  /* initial values of the ratio    */
  /**********************************/

  int    r_from;                /**< from to compute Rref */
  int    r_to;                  /**< to to compute Rref */
  double r_val;                 /**< value to cimpute Rref */

  /**********************************/
  /*    connectivity of processor   */
  /*    in the application graph    */
  /**********************************/

  int*       rpro;		/**< gives the vertex id that is assigned to a processor in app, vtx = rpro[pro] (reverse of pro = pro[vtx]) */
  GraphType* app;		/**< subdomain connectivity graph */

  /******************/
  /** -- REMOVE -- **/
  int **realnetcost;		/**< Real Network Cost matrix*/
  int **netcost;		/**< matrix that is used in refinement (was used when quadratic path length was studied could be removed)*/
  double *proratio;		/**< Execution time Ratio for each processors*/
  double *proportion;		/**< Processor weighting for each processors*/
  double *prospeed;             /**< 1/proportion */
  int *penalty;			/**< penalty weight for each processors*/  
  /** -- END REMOVE -- **/
  /**********************/

  int maxdegree;		/**< average degree to processor graph*/
}GridType;

/************************************************************************/
/* coarsening specific structures 					*/
/** \brief coarsening phase control structure */
typedef struct CoaCtrl{
  GraphType* g;			/**< application graph */
  int          npro;	  	/**< number of processors */
  int          maxvwgt;	 	/**< maximum weight a matched vertex can have */
  int*         label;           /**< array of size nvtxs (used by MHEM) */
  int          randguide;	/**< if random numbers are used (could be removed) */
  int*         guide;		/**< random guide to visit vertices */
  PartInfoType *info;		/**< other info */
}CoaCtrl;

/*************************************************************************/
/* initial partitioning specific structures 				 */
/** \brief edge structure, the two endpoints might be swapped during the swapping stage */
typedef struct SwapEdge{
  int   prov;
  int   prow;
  void* pos;
}SwapEdge;
/** \brief swapping stage control structure */
typedef struct SwapCtrl{
  GraphType* g;
  GridType*  n;

  SwapEdge*	edges;		/**< edges[edge] gives each end of an edge */
  double*	pexec;		/**< array to get variations in exec per proc*/
  Heap*		heap;		/**< heap */

  double	tmax;		/**< maximum execution time */

}SwapCtrl;

/*************************************************************************/
/* uncoarsening specific structures */
/** \brief information about a reassignement */
typedef struct vRef{
  struct vRef** pos;

  int    idx;		/**< vertex index */
  int    from;		/**< origin of reassignement */
  int    to;		/**< destination of reassignment */

  double deltaF;	
  double deltaT;
  double deltaO;
  
  int    dOflag;	/**< if deltaO is 0 tell if we need to scan other adj proc */

  struct vRef* n;	/**< next entry of the same vertex index in boundaries */
  struct vRef* p;	/**< previous entry of the same vertex index in boundaries */
}vRef;

/** \brief container of boundary vertices */
typedef struct vRefCont{
  int   max_s;  /**< maximum size before reallocation */
  int   s;	/**< current size */
  vRef* arr;    /**< array of boundary vertices */
}vRefCont;

typedef int    (FILTER_FN)(void* rctrl,int a,int v,int from,int to,
			   double deltaF,double deltaT,double deltaO,int dOflag);
typedef double (GAIN_FN)  (void* rctrl,vRef* vref);
typedef int    (UNDO_FN)  (void* rctrl,int action,vRef* v);
/** \brief Uncoarsening control structure */
typedef struct RefCtrl{
  GraphType* g;
  GridType*  n;


  FILTER_FN* filter_fn; /**< Filter function to use to put vertices into 
			   the heap and to apply a move */
  UNDO_FN*   undo_fn;   /**< Undo function to use to find out when we 
			   need to undo move for a better one */
  GAIN_FN*   gain_fn;

  int*       procs;	/**< temporary array to store the sum of edge weight that connect a vertex to each processor's subdomain */
  int*       procon;    /**< temporary array to store the number of edges that connect a vertex to each processor's subdomain */
  int*       procs2;    /**< same as procs */
  int*       procon2;   /**< same as procon */
  double*    flow;      /**< store executime time before load balancing to restrict direction of reassignments */
  double*    exec;      /**< temporary array to check increase in max exectime */
  int*       mvtxs;     /**< count the number of moves for each vertex */

  int*       guide;	/**< unused */

  /* refinement info */
  vRef*      bnds;	/**< head of dll that point inside containers (one for each vertex) */
  int	     nrvtxs;    /**< number of boundaries */
  vRef**     rvtxs;	/**< array of pointer to refinement info, this represents the information in the move heap */
  vRefCont*  proref;	/**< containers of boundary vertices (one per processor) */
  
  /* recent move list */
  int	     nb_undo;   /**< number of vertices in the recent move list */
  vRef*      undo;	/**< recent move list */

  /* heaps */
  Heap*	     heap;  	/**< move heap */
  Heap*      pheap;	/**< processor heap */

  int    level;		/**< current level of uncoarsening */
  double tmean;		/**< average execution time */
  double tmax;	 	/**< maximum execution time */
  double tmin;		/**< minimum execution time */
  double t;		/**< total execution time */
  double im;		/**< imbalance */
  double imthreshold;	/**< imbalance tolerance */
  
}RefCtrl;
#endif
